<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="QhmSx" id="QhmSx"><span data-lake-id="u352186cf" id="u352186cf">典型回答</span></h1>
  <p data-lake-id="ud403f719" id="ud403f719"><br></p>
  <p data-lake-id="u4441ad9a" id="u4441ad9a"><span data-lake-id="ue0ff1ce1" id="ue0ff1ce1">Redis提供了两种持久化的机制，分别是RDB和AOF。</span></p>
  <h3 data-lake-id="im7rs" id="im7rs"><span data-lake-id="u0aceb44c" id="u0aceb44c">RDB</span></h3>
  <p data-lake-id="u479538f6" id="u479538f6"><span data-lake-id="u0ea38aa5" id="u0ea38aa5">RDB是将Redis的内存中的数据</span><strong><span data-lake-id="ue4bda565" id="ue4bda565">定期</span></strong><span data-lake-id="u74aa6849" id="u74aa6849">保存到磁盘上，以防止数据在Redis进程异常退出或服务器断电等情况下丢失。</span></p>
  <p data-lake-id="ubb558bd1" id="ubb558bd1"><span data-lake-id="ubb9ff01d" id="ubb9ff01d">​</span><br></p>
  <p data-lake-id="u4c55cd02" id="u4c55cd02"><strong><span data-lake-id="u02a47d74" id="u02a47d74">RDB的优点是：快照文件小、恢复速度快，适合做备份和灾难恢复。</span></strong></p>
  <p data-lake-id="u0c03c312" id="u0c03c312"><strong><span data-lake-id="u5c059583" id="u5c059583">RDB的缺点是：定期更新可能会丢数据</span></strong></p>
  <p data-lake-id="u7a6fbb24" id="u7a6fbb24"><span data-lake-id="ua49108a1" id="ua49108a1">​</span><br></p>
  <h3 data-lake-id="YqNNT" id="YqNNT"><span data-lake-id="u8167fdff" id="u8167fdff">AOF</span></h3>
  <p data-lake-id="ucc026d2c" id="ucc026d2c"><br></p>
  <p data-lake-id="u1adc136e" id="u1adc136e"><span data-lake-id="u9b02e574" id="u9b02e574">AOF是将Redis的所有写操作</span><strong><span data-lake-id="udfba122a" id="udfba122a">追加到AOF文件（Append Only File）的末尾，</span></strong><span data-lake-id="u15124ce6" id="u15124ce6">从而记录了Redis服务器运行期间所有修改操作的详细记录。当Redis重新启动时，可以通过执行AOF文件中保存的写操作来恢复数据。</span></p>
  <p data-lake-id="uf35397ef" id="uf35397ef"><span data-lake-id="ud9889d80" id="ud9889d80">​</span><br></p>
  <p data-lake-id="u9408cff6" id="u9408cff6"><span data-lake-id="ud0264ad9" id="ud0264ad9">但是如果Redis刚刚执行完一个写命令，还没来得及写AOF文件就宕机了，那么这个命令和相应的数据就会丢失了。但是他也比RDB要更加靠谱一些。</span></p>
  <p data-lake-id="u5ca4b7ae" id="u5ca4b7ae"><span data-lake-id="u9352e752" id="u9352e752">​</span><br></p>
  <p data-lake-id="u90bca172" id="u90bca172"><strong><span data-lake-id="ucb54ff56" id="ucb54ff56">AOF的优点是：可以实现更高的数据可靠性、支持更细粒度的数据恢复，适合做数据存档和数据备份。</span></strong></p>
  <p data-lake-id="u95e19cba" id="u95e19cba"><strong><span data-lake-id="u011fb308" id="u011fb308">AOF的缺点是：文件大占用空间更多，每次写操作都需要写磁盘导致负载较高</span></strong></p>
  <p data-lake-id="ued2c4b1a" id="ued2c4b1a"><strong><span data-lake-id="ue409d491" id="ue409d491">​</span></strong><br></p>
  <h3 data-lake-id="nrzJq" id="nrzJq"><span data-lake-id="udfabbf89" id="udfabbf89">比较</span></h3>
  <p data-lake-id="u3d23f017" id="u3d23f017"><br></p>
  <p data-lake-id="u0fe3169d" id="u0fe3169d"><span data-lake-id="u133bdb40" id="u133bdb40">RDB和AOF在数据可靠性、性能、存储空间占用等方面都有不同的优缺点，具体可以根据实际业务需求和硬件条件来选择合适的持久化机制，或者同时使用两种持久化机制来实现更高的数据可靠性。</span></p>
  <p data-lake-id="udec5c34d" id="udec5c34d"><span data-lake-id="uc34a843d" id="uc34a843d">​</span><br></p>
  <table data-lake-id="z05wc" id="z05wc" margin="true" class="lake-table" style="width: 750px">
   <colgroup>
    <col width="250">
    <col width="250">
    <col width="250">
   </colgroup>
   <tbody>
    <tr data-lake-id="u19202c1d" id="u19202c1d">
     <td data-lake-id="u27641d4b" id="u27641d4b">
      <p data-lake-id="u50caea60" id="u50caea60"><strong><span data-lake-id="u660a0ee1" id="u660a0ee1">特性</span></strong></p></td>
     <td data-lake-id="ue21a1f84" id="ue21a1f84">
      <p data-lake-id="ub8d7f4ba" id="ub8d7f4ba"><strong><span data-lake-id="u538aa65d" id="u538aa65d">RDB</span></strong></p></td>
     <td data-lake-id="ub34825ab" id="ub34825ab">
      <p data-lake-id="u04564de6" id="u04564de6"><strong><span data-lake-id="uadd4f675" id="uadd4f675">AOF</span></strong></p></td>
    </tr>
    <tr data-lake-id="u2616e196" id="u2616e196">
     <td data-lake-id="u2e035eff" id="u2e035eff">
      <p data-lake-id="u6d4312f1" id="u6d4312f1"><span data-lake-id="ucc3eb63e" id="ucc3eb63e">数据可靠性</span></p></td>
     <td data-lake-id="ucc17b92e" id="ucc17b92e">
      <p data-lake-id="u32d615bf" id="u32d615bf"><span data-lake-id="ubdd36bb4" id="ubdd36bb4">可能会丢失最后一次快照之后的数据</span></p></td>
     <td data-lake-id="u7996f3f6" id="u7996f3f6">
      <p data-lake-id="uc944bf01" id="uc944bf01"><span data-lake-id="ufcc14f8b" id="ufcc14f8b">保证最后一次写操作之前的数据不会丢失</span></p></td>
    </tr>
    <tr data-lake-id="ue5148c28" id="ue5148c28">
     <td data-lake-id="ued0f05dd" id="ued0f05dd">
      <p data-lake-id="ubf2418f6" id="ubf2418f6"><span data-lake-id="ue52a0758" id="ue52a0758">性能</span></p></td>
     <td data-lake-id="u4e906b35" id="u4e906b35">
      <p data-lake-id="ud941ff6b" id="ud941ff6b"><span data-lake-id="u72d3848d" id="u72d3848d">读写性能较高，适合做数据恢复</span></p></td>
     <td data-lake-id="u9ffa58ba" id="u9ffa58ba">
      <p data-lake-id="u104cd941" id="u104cd941"><span data-lake-id="ufcc6784c" id="ufcc6784c">写性能较高，适合做数据存档</span></p></td>
    </tr>
    <tr data-lake-id="ufe9ba104" id="ufe9ba104">
     <td data-lake-id="uf46d09f8" id="uf46d09f8">
      <p data-lake-id="u94c8e898" id="u94c8e898"><span data-lake-id="u9dffda08" id="u9dffda08">存储空间占用</span></p></td>
     <td data-lake-id="uf819ea43" id="uf819ea43">
      <p data-lake-id="uc869416f" id="uc869416f"><span data-lake-id="ub286bdc3" id="ub286bdc3">快照文件较小，占用空间较少</span></p></td>
     <td data-lake-id="uf795390e" id="uf795390e">
      <p data-lake-id="u54b33280" id="u54b33280"><span data-lake-id="u201c994d" id="u201c994d">AOF文件较大，占用空间较多</span></p></td>
    </tr>
    <tr data-lake-id="u42ae2cf3" id="u42ae2cf3">
     <td data-lake-id="u3a069786" id="u3a069786">
      <p data-lake-id="u8aa28359" id="u8aa28359"><span data-lake-id="ud0d2951b" id="ud0d2951b">恢复时间</span></p></td>
     <td data-lake-id="u9cf45ee0" id="u9cf45ee0">
      <p data-lake-id="u4dcb3757" id="u4dcb3757"><span data-lake-id="u8c0239c4" id="u8c0239c4">从快照文件中恢复数据较快</span></p></td>
     <td data-lake-id="u3ac5704b" id="u3ac5704b">
      <p data-lake-id="u6f3c108c" id="u6f3c108c"><span data-lake-id="uaab73128" id="uaab73128">从AOF文件中恢复数据较慢</span></p></td>
    </tr>
   </tbody>
  </table>
  <p data-lake-id="ubd1e857a" id="ubd1e857a"><span data-lake-id="u0e7d3f5e" id="u0e7d3f5e">​</span><br></p>
  <h3 data-lake-id="rRGxc" id="rRGxc"><span data-lake-id="ub6ef848d" id="ub6ef848d">混合持久化</span></h3>
  <p data-lake-id="u3065a889" id="u3065a889"><br></p>
  <p data-lake-id="u148bb635" id="u148bb635"><span data-lake-id="uadef8fb7" id="uadef8fb7">AOF和RDB各自有优缺点，为了让用户能够同时拥有上述两种持久化的优点， Redis 4.0 推出了 RDB-AOF 混合持久化。</span></p>
  <p data-lake-id="u2bfced0f" id="u2bfced0f"><span data-lake-id="u9282713e" id="u9282713e">​</span><br></p>
  <p data-lake-id="u9eca8a6a" id="u9eca8a6a"><span data-lake-id="ub1a36cb3" id="ub1a36cb3">在开启混合持久化的情况下，AOF 重写时会把 Redis 的持久化数据，以 RDB 的格式写入到 AOF 文件的开头，之后的数据再以 AOF 的格式化追加的文件的末尾。</span></p>
  <p data-lake-id="ucea31102" id="ucea31102"><span data-lake-id="ud153a79d" id="ud153a79d">​</span><br></p>
  <p data-lake-id="ubda5dff1" id="ubda5dff1"><code data-lake-id="u4cfc1328" id="u4cfc1328"><span data-lake-id="udf901020" id="udf901020">aof-use-rdb-preamble</span></code><span data-lake-id="ud7ef2e07" id="ud7ef2e07">是开启混合模式的参数</span></p>
  <p data-lake-id="ua9cb1a9a" id="ua9cb1a9a"><br></p>
  <p data-lake-id="u5bb1c83c" id="u5bb1c83c"><span data-lake-id="u71a73d65" id="u71a73d65" class="lake-fontsize-12" style="color: rgb(59, 67, 81)">混合持久化结合了 RDB 和 AOF 持久化的优点，开头为 RDB 的格式，使得 Redis 可以更快的启动，同时结合 AOF 的优点，有减低了大量数据丢失的风险。</span></p>
  <p data-lake-id="u3dcabeb9" id="u3dcabeb9"><strong><span data-lake-id="u2fa56d43" id="u2fa56d43" class="lake-fontsize-12" style="color: rgb(59, 67, 81)">​</span></strong><br></p>
  <p data-lake-id="u0f5f8cf5" id="u0f5f8cf5"><span data-lake-id="ub125a46c" id="ub125a46c" class="lake-fontsize-12" style="color: rgb(59, 67, 81)">但是，在AOF 文件中添加了 RDB 格式的内容，使得 AOF 文件的</span><strong><span data-lake-id="u379605b1" id="u379605b1" class="lake-fontsize-12" style="color: rgb(59, 67, 81)">可读性变得很差</span></strong><span data-lake-id="uf6343b5c" id="uf6343b5c" class="lake-fontsize-12" style="color: rgb(59, 67, 81)">；如果开启混合持久化，那么此混合持久化 AOF 文件，是不能用在旧版本中的，</span><strong><span data-lake-id="u1c2548d1" id="u1c2548d1" class="lake-fontsize-12" style="color: rgb(59, 67, 81)">不向下兼容</span></strong><span data-lake-id="uac92df9f" id="uac92df9f" class="lake-fontsize-12" style="color: rgb(59, 67, 81)">的。</span></p>
  <p data-lake-id="u53e51f1d" id="u53e51f1d"><br></p>
  <h1 data-lake-id="w0Aj5" id="w0Aj5"><span data-lake-id="ufa2a0f93" id="ufa2a0f93">扩展知识</span></h1>
  <p data-lake-id="ub38816f7" id="ub38816f7"><br></p>
  <h2 data-lake-id="CRcGZ" id="CRcGZ"><span data-lake-id="uc7344f85" id="uc7344f85">Redis能完全保证数据不丢失吗？</span></h2>
  <p data-lake-id="ue6da4c69" id="ue6da4c69"><br></p>
  <p data-lake-id="u5af80e98" id="u5af80e98"><span data-lake-id="u09fba131" id="u09fba131">不能，因为Redis是基于内存存储的，当Redis进程异常退出或服务器断电等情况发生时，内存中的数据可能会丢失。</span></p>
  <p data-lake-id="u4282487b" id="u4282487b"><span data-lake-id="u3fd5b364" id="u3fd5b364">​</span><br></p>
  <p data-lake-id="ua0db1961" id="ua0db1961"><span data-lake-id="ue40e5f39" id="ue40e5f39">为了防止数据丢失，Redis提供了RDB和AOF的持久化机制，Redis可以将数据从内存保存到磁盘中，以便在Redis进程异常退出或服务器断电等情况下，通过从磁盘中加载数据来恢复数据。</span></p>
  <p data-lake-id="u8977d14b" id="u8977d14b"><span data-lake-id="u7c6dc3f9" id="u7c6dc3f9">​</span><br></p>
  <p data-lake-id="u7da2de3b" id="u7da2de3b"><span data-lake-id="u2026146f" id="u2026146f">但是，持久化机制也不是绝对可靠的，归根结底Redis还是个缓存，他并不是完全给你做持久化用的，所以还是要有自己的持久化方式，比如双写到数据库。</span></p>
  <p data-lake-id="u02f7964e" id="u02f7964e"><span data-lake-id="u641e3bc8" id="u641e3bc8">​</span><br></p>
  <p data-lake-id="u0a5b64ee" id="u0a5b64ee"><span data-lake-id="u67919490" id="u67919490">因此，为了最大程度地保障数据安全，建议采用多种手段来提高数据可靠性，如定期备份数据、使用主从复制机制、使用集群模式等。</span></p>
  <p data-lake-id="u7763307e" id="u7763307e"><span data-lake-id="u0ac86423" id="u0ac86423">​</span><br></p>
  <p data-lake-id="u1e35aa79" id="u1e35aa79"><span data-lake-id="ua004f2c5" id="ua004f2c5">​</span><br></p>
  <h2 data-lake-id="yxq2a" id="yxq2a"><span data-lake-id="u03f9442d" id="u03f9442d">AOF的三种写回策略</span></h2>
  <p data-lake-id="u307daa4a" id="u307daa4a"><br></p>
  <p data-lake-id="u113865a6" id="u113865a6"><span data-lake-id="u6d1eb351" id="u6d1eb351">AOF有三种数据写回策略，分别是Always，Everysec和No。</span></p>
  <p data-lake-id="uefa1b7e1" id="uefa1b7e1"><span data-lake-id="u50098d7f" id="u50098d7f">​</span><br></p>
  <ul list="uf0d7add4">
   <li fid="u21e11e3d" data-lake-id="uc8ba46b4" id="uc8ba46b4"><strong><span data-lake-id="u9116acca" id="u9116acca">Always</span></strong><span data-lake-id="u4c0fcc68" id="u4c0fcc68">，同步写回：每个写命令执行完，立马同步地将日志写回磁盘；</span></li>
   <li fid="u21e11e3d" data-lake-id="u430893b2" id="u430893b2"><strong><span data-lake-id="u8fb49eb2" id="u8fb49eb2">Everysec</span></strong><span data-lake-id="u449af08d" id="u449af08d">，每秒写回：每个写命令执行完，只是先把日志写到AOF文件的内存缓冲区，每隔一秒把缓冲区中的内容写入磁盘；</span></li>
   <li fid="u21e11e3d" data-lake-id="u33078de7" id="u33078de7"><strong><span data-lake-id="u157506e6" id="u157506e6">No</span></strong><span data-lake-id="u0581f0bd" id="u0581f0bd">，操作系统控制的写回：每个写命令执行完，只是先把日志写到AOF文件的内存缓冲区，由操作系统决定何时将缓冲区内容写回磁盘。</span></li>
  </ul>
  <p data-lake-id="u7c59ffea" id="u7c59ffea"><span data-lake-id="u0a707aef" id="u0a707aef">​</span><br></p>
  <p data-lake-id="ud3c9c39e" id="ud3c9c39e"><span data-lake-id="u0cbcfe99" id="u0cbcfe99">“同步写回”可靠性肯定是最高的，但是它在每一个写命令后都有一个落盘操作，而且还是同步的，这和直接写磁盘类型的数据库有啥区别？</span></p>
  <p data-lake-id="ufb83e2b6" id="ufb83e2b6"><span data-lake-id="uf5344816" id="uf5344816">​</span><br></p>
  <p data-lake-id="u4cd9aa16" id="u4cd9aa16"><span data-lake-id="u14bf60e4" id="u14bf60e4">"操作系统控制的写回"这种是最不靠谱的，谁知道操作系统啥时候帮你做持久化，万一没来及持久化就宕机了，不就gg了。</span></p>
  <p data-lake-id="ub64c6a57" id="ub64c6a57"><span data-lake-id="ue74748b7" id="ue74748b7">​</span><br></p>
  <p data-lake-id="uf488993f" id="uf488993f"><span data-lake-id="u095a9741" id="u095a9741">"每秒写回"是在二者之间折中了一下，异步的每秒把数据写会到磁盘上，最大程度的提升效率和降低风险。</span></p>
  <p data-lake-id="u254a7b20" id="u254a7b20"><span data-lake-id="u938f7203" id="u938f7203">​</span><br></p>
  <h3 data-lake-id="MiloB" id="MiloB"><span data-lake-id="u2113bd80" id="u2113bd80">Always也不能保证不丢</span></h3>
  <p data-lake-id="u51fd2490" id="u51fd2490"><br></p>
  <p data-lake-id="u240c607f" id="u240c607f"><span data-lake-id="u8a2ec268" id="u8a2ec268">即使是在always策略下，也不能保证100%不丢失数据的，主要出于以下原因：</span></p>
  <p data-lake-id="u2c002073" id="u2c002073"><span data-lake-id="u2bdd6adb" id="u2bdd6adb">​</span><br></p>
  <ol list="u47b62a63">
   <li fid="u7cd0de49" data-lake-id="uf5c61636" id="uf5c61636"><strong><span data-lake-id="u2081de75" id="u2081de75">磁盘和系统故障</span></strong><span data-lake-id="u26c4195d" id="u26c4195d">：如果在写入操作和同步到磁盘之间发生硬件故障或系统崩溃，可能会丢失最近的写操作。</span></li>
  </ol>
  <p data-lake-id="u7ce77969" id="u7ce77969"><br></p>
  <ol list="u47b62a63" start="2">
   <li fid="u7cd0de49" data-lake-id="udc1cf811" id="udc1cf811"><strong><span data-lake-id="ucdce0a85" id="ucdce0a85">操作系统缓冲区</span></strong><span data-lake-id="u4e0a1ad8" id="u4e0a1ad8" class="lake-fontsize-12" style="color: var(--text-primary)">：即使Redis请求立即将数据同步到磁盘，操作系统的I/O缓冲区可能会导致实际写入磁盘的操作延迟发生。如果在写入缓冲区之后，没写磁盘前，机器挂了，那么数据就丢了。</span></li>
  </ol>
  <p data-lake-id="u61bd1ed1" id="u61bd1ed1"><br></p>
  <blockquote data-lake-id="u625c99fb" id="u625c99fb">
   <p data-lake-id="u9d47742a" id="u9d47742a"><span data-lake-id="u3ef376cb" id="u3ef376cb" class="lake-fontsize-12" style="color: rgb(15, 15, 15)">操作系统缓冲区，通常指的是操作系统用于管理数据输入输出（I/O）的一种内存区域。当程序进行文件写入操作时，数据通常首先被写入到这个缓冲区，而不是直接写入到硬盘。</span></p>
  </blockquote>
  <p data-lake-id="u563ab4a6" id="u563ab4a6"><br></p>
  <ol list="u47b62a63" start="3">
   <li fid="u7cd0de49" data-lake-id="ud35ac65d" id="ud35ac65d"><strong><span data-lake-id="uf5aff460" id="uf5aff460">磁盘写入延迟</span></strong><span data-lake-id="ub9b3cf5c" id="ub9b3cf5c">：磁盘的写入并非实时完成，特别是在涉及到机械硬盘时，写入延迟主要由磁盘旋转速度（RPM）和寻道时间决定。如果在这这个延迟过程中，机器挂了，那么数据也就丢了。</span></li>
  </ol>
  <p data-lake-id="ud917bb09" id="ud917bb09"><br></p>
  <p data-lake-id="u36725f64" id="u36725f64"><br></p>
 </body>
</html>